#include "TcpServer.h"
#include "Connection.h"

TcpServer::TcpServer(const std::string &ip, const uint16_t port)
{
    acceptor_ = new Acceptor(&loop_, ip, port);
    acceptor_->setnewconnectioncb(std::bind(&TcpServer::newconnection, this, std::placeholders::_1));
    loop_.setepolltimeoutcallback(std::bind(&TcpServer::epolltimeout,this,std::placeholders::_1));
}

TcpServer::~TcpServer()
{
    delete acceptor_;
    for (auto &aa : conns_)
    {
        delete aa.second;
    }
}

void TcpServer::start()
{
    loop_.run();
}

void TcpServer::newconnection(Socket *clientsock)
{
    Connection *conn = new Connection(&loop_, clientsock);
    conn->setclosecallback(std::bind(&TcpServer::closeconnection, this, std::placeholders::_1));
    conn->seterrorcallback(std::bind(&TcpServer::errorconnection, this, std::placeholders::_1));

    conn->sethaddlemsgcallback(std::bind(&TcpServer::haddlemessage, this, std::placeholders::_1, std::placeholders::_2));

    conn->setsendcompletecallback(std::bind(&TcpServer::sendcomplete,this,std::placeholders::_1));

    printf("New client connected: %s:%d\n", conn->ip().c_str(), conn->port());
    conns_[conn->fd()] = conn;
}

void TcpServer::closeconnection(Connection *conn)
{
    printf("client(eventfd=%d)disconnected\n", conn->fd());
    // close(conn->fd());
    conns_.erase(conn->fd());
    delete conn;
}
void TcpServer::errorconnection(Connection *conn)
{
    printf("else error\n");
    // close(conn->fd());
    conns_.erase(conn->fd());
    delete conn;
}

// 处理数据的逻辑放到这里
void TcpServer::haddlemessage(Connection *conn, std::string message)
{
    message = "replay:" + message;
    int len = message.size();

    std::string tmpbuf((char *)&len, 4);
    tmpbuf.append(message);

    //write(conn->fd(), tmpbuf.data(), tmpbuf.size());
    conn->send(tmpbuf.data(), tmpbuf.size());
}


void TcpServer::sendcomplete(Connection *conn)
{
    printf("send complete\n");
    // 根据业务需求，可增加其它代码
}


void TcpServer::epolltimeout(EventLoop *loop)
{
    printf("epoll_wait() timeout\n");

    // 根据业务需求，可以增加其他代码
}